﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
#if !SERVER
using Warensoft.Unity.Communication.Client;
#endif

using System.IO;

namespace Warensoft.Unity.Communication.Client.DataClient
{

    public class DataEntity
    {
#if !SERVER
        public Dictionary<string, DataEntitySet> ChildTables;


        DataContext currentContext;
#endif
        internal Guid UpdateStub { get; set; }
        internal bool isNew = false;
        private DataPropertySet properties = new DataPropertySet();
        public DataPropertySet Properties
        {
            get
            {
                return this.properties;
            }
        }
        internal EntityState state;
        public EntityState State
        {
            get
            {
                return this.state;
            }
        }
        private string tableName;

        public string TableName
        {
            get { return tableName; }
            
        }

        internal DataEntity()
        { }

#if !SERVER

        internal DataEntity(DataRow row, DataContext currentContext)
        {
            this.currentContext = currentContext;
                        this.tableName = row.Table.TableName;

            foreach (DataColumn col in row.Table.Columns)
            {
                if (this.currentContext.dsSchema.Tables[this.tableName].PrimaryKey.Count(key => key.ColumnName == col.ColumnName)!=0)
                {
                    this.properties.Add(new DataProperty(col.ColumnName, row[col.ColumnName],true) );
                }
                else
                {
                    this.properties.Add(new DataProperty(col.ColumnName, row[col.ColumnName]));
                }
            }
            this.ChildTables = new Dictionary<string, DataEntitySet>();

            foreach (DataRelation relation in row.Table.ChildRelations)
            {

                this.ChildTables.Add(relation.ChildTable.TableName, new DataEntitySet(this.currentContext, relation.ChildTable, true));
            }
            this.state = EntityState.Unchanged;
        } 
#endif
        
        public object this[string columnName]
        {
            get
            {
                return this.properties[columnName].Value;
            }
            set
            {
                if (this.properties[columnName].Value.Equals(value)==false )
                {
                    if (!this.isNew)
                    {
                        this.state = EntityState.Changed;
                    }
                    this.properties[columnName].Value = value;
                
                }
                
            }
        }
        public void Delete()
        {
            this.state = EntityState.Deleted;
        }
        public void AcceptChanges()
        {
            this.isNew = false;
            this.state = EntityState.Unchanged;
        }

        public static DataEntity Create(byte[] buffer)
        {
            DataEntity entity = new DataEntity();
            using (MemoryStream ms=new MemoryStream (buffer))
            {
                using (BinaryReader br=new BinaryReader (ms))
                {
                    entity.tableName = br.ReadString();
                    entity.state = (EntityState)br.ReadByte();
                    int propertyBufferLength = br.ReadInt32();
                    byte[] propertyBuffer=new byte[propertyBufferLength];
                    br.Read(propertyBuffer, 0, propertyBufferLength);
                    entity.properties = DataPropertySet.Create(propertyBuffer);
                }
            }
            return entity;
        }
        public byte[] ToArray()
        {
            byte[] buffer = null;

            using (MemoryStream ms=new MemoryStream ())
            {
                using (BinaryWriter bw=new BinaryWriter (ms))
                {
                    bw.Write(this.tableName );
                    bw.Write((byte)this.state);
                    var propertiesBuffer = this.properties.ToArray();
                    bw.Write(propertiesBuffer.Length );
                    bw.Write(propertiesBuffer,0, propertiesBuffer.Length );
                }
                buffer = ms.ToArray();
            }
            return buffer;
        }
    }

    
}
